一、MongoDB聚合函数说明
max()与min()
通常总是需要找到给定集合里的某个字段的最大值与最小值。使用sql的数据库则给我们提供了max()与min()函数,但是Mongodb并没有提供这样的函数,所以我们必须自己实现。如果要找到某个字段的最大值,可以按照该字段降序排序,并限制结果集为一个文档;同时,按照相反顺序排序则会获取到该字段的最小值。因此,在monogoDB中的max()与min()则需要对某字段进行排序并限制返回文档数为一即可。(利用sort进行排序-1代表降序,1代表升序。)
#返回最大值
db.test_test.find().sort({rand:-1}).limit(1)
#返回最小值
db.test_test.find().sort({rand:-1}).limit(1)
注意:在实际生产环境中,利用sort排序的时候最好对排序字段加上索引,如果数据量不大,索引与否影响不大,如果数据量大的话,索引的存在对效率影响将是巨大的。
-
distinct
MongoDB的distinct命令是获取特定字段中不同值列表的最简单工具。该命令既适用于单键,也适用于数组键。distinct默认覆盖整个集合,但也可以通过查询选择器进行约束。如下 **db.test_test.distinct("rand");**
这个比较简单。如果希望操作集合的子集,那么我们可以传入一个查询选择器作为第二个参数。如下:
**db.test_test.distinct("rand", {number:5});** 注意:在实用性的方面,distinct与group有一个很大的限制:它们返回的结果集不能超过16MB。16MB的限制并不是这些命令本身所强加的的阈值,这是所有的初始查询结果集大小。distinct与group是以命令的方式实现的,也就是对特殊$cmd集合的查询,它们赖以生成的查询受制于该限制。如果distinct与group处理不了你的聚合的结果集,那么只能用map-reduce代替了,它的结果可以保存在集合中而非内联(inline)返回。
group
group和distinct一样,也是数据库命令,因此它的结果集也受制于16MB的响应限制。而且,为了减少内存消耗,group不会处理多于10000个唯一键。如果聚合操作在此范围内,选择使用group会比使用map-reduce效率高些。group最少需要三个参数。第一个参数是key,定义如何对数据进行分组。第二个参数是一个对结果集做聚合的Javascript函数,叫reduce函数。第三个分组参数是reduce函数的初始文档。
result = db.test_test.group({
key: {number:true},
initial: {rand:0, count:0},
reduce: function(obj, prev){
prev.count += 1;
prev.rand += obj.rand;
}
})
PHP中的group简单应用:
# use all fields
$keys = array();
# set intial values
$initial = array("count" => 0);
# JavaScript function to perform
$reduce = "function (obj, prev) { prev.count++; }";
# only use documents where the "a" field is greater than 1
$condition = array("a" => array( '$gt' => 1));
$g = $collection->group($keys, $initial, $reduce, $condition);
group选项解释:
key:描述分组字段的文档。键的样式为:{rand:true, number:true}。除非使用keyf,否则key选项是必需的。
keyf:这是一个JavaScript函数,应用于文档之上,为该文档生成一个键,当用于分组的键需要计算时,这个函数非常有用。如:function(doc){return
{day:doc.created_at.getDay();}}。如果没有指定标准的key的话,则keyf是必需的。
initial:作为聚合结果初始文档。reduce函数第一次运行时,该初始文档会作为聚合器的第一个值,通常会包含所有要聚合的键。例:{rand:0, count:0}
reduce:用于执行聚合的JavaScript函数。该函数接受两个参数:正初迭代的当前文档和用于存储聚合结果的聚合器文档。如上例的应用,注意:reduce函数并不返回任何内容,它只不过是修改聚合器对象,该参数是必需的。
cond:过滤要聚合文档的查询选择器,不多解释了。
finalize:在返回结果集之前应用于每个结果文档的JavaScript函数。该函数支持对分组操作的结果进行后置处理。
map-reduce
在添加map-reduce之前,group是MongoDB唯一的聚合器。map-reduce是后来出于一些原因加入的。首先,MapReduce风格的操作正在成为主流(很多开发者是在谷歌那篇著名的关于分布工计算的论文初次看到MapReduce的。其中的思想后来成了Hadoop的基础,而Hadoop是一个使用分布式MapReduce处理大数据的开源框架)。实际原因,对大数据集进行迭代,尤其是在分片配置中,需要有分布式的聚合器,而MapReduce恰恰提供把需的内容。
PHP中的map-reduce的应用:
$query = array('qq_bind_info.openid'=>array('$exists'=>1));
$map = new MongoCode('function(){emit(this.qq_bind_info.openid, {uid:this._id, step:1})}');
$reduce = new MongoCode("function(key, vals){".
"var user_list = new Array();" .
"var open_id = new Array();" .
"var sum = 0;" .
"vals.forEach(function(value){" .
"sum += value.step;" .
"open_id.push(key);" .
"user_list.push(value.uid);" .
"});" .
"return {userlist:user_list, openid:open_id, sum:sum};}");
$data = $db->command(array(
'mapreduce' => 'user_profile',
'map' => $map,
'reduce' => $reduce,
'query' => $query,
'out' => 'user_profile_temp'
));
print_r($data);
map-reduce选项解释:
map:应用于每个文档之上的JavaScript函数。该函数必须调用emit()来选择要聚合的键和值。在函数上下文中,this的值指向当前文档。例如:function(){emit(this.qq_bind_info.openid,{uid:this._id, step:1})}
reduce:一个JavaScript函数,接受一个键和一个值列表。该函数对返回值的结构有严格要求,必须总是与values数组所提供的结构一致。如上$reduce的MongoCode中的function。
query:用于过滤处理的集合的查询选择器。与group的con参数相同。 sort:对查询的排序。
limit:一个整数,指定了查询和排序的条数。
out:这个参数决定了如何返回输出内容。如果需要将输出作为命令的返回结果,则需要传入{inline:true}。注意:这个仅适用于结果集在16MB以内的情况。另一个选择是将结果放到一个集合里,则out参数则是字符串,即集合的名称。
finalize:一个JavaScript函数,在reduce阶段完成后会应用于每个返回的文档上。
scope:该文档指定了map、reduce和finalize函数可全局访问的变量的值。
verbose:一个布尔值,为true时,在命令返回文档中会包含对map-reduce任务执行时间的统计信息。
注意:在out参数为存入到新的集合时,会有一个问题:如果最近有运行过类似的map-reduce,那么可能会覆盖现有数据。因此,还有两个集合输出选项:一个用于合并结果和老数据;另一个对数据进行reduce处理。合并的场景中,使用{merge:'collectionName'},新结果会覆盖拥有相同键的现有项。如果使用{reduce:'collectionName'},会调用reduce函数根据新值来处理现有的键值
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。